package Persistance.KMeans;

import java.util.Vector;

public class ClusterAnalysis
{
    private static final int MAX = 18;
    private Cluster[]		_clusters;
	private int				_iterator;
	private Vector<Point>	_points	= new Vector<Point>();
	private double			_SWCSS;

	public ClusterAnalysis(int k, int iter, Vector<Point> dataPoints)
	{
		_clusters = new Cluster[k];
		for (int i = 0; i < k; i++)
		{
			_clusters[i] = new Cluster("Cluster" + i);
		}
		this._iterator = iter;
		this._points = dataPoints;
	}

	
	private void calcSWCSS()
	{
		double temp = 0;
        for (Cluster _cluster : _clusters) {
            temp += _cluster.getSumSqr();
        }
        _SWCSS = temp;
	}

	public void startAnalysis()
	{
		InitialCentroids();
		int n = 0;

        while(n < _points.size()){
            for(int c=0; ((c<_clusters.length) && (n < _points.size())) ; c++){
                _clusters[c].AddPoint(_points.elementAt(n));
                n++;
            }
        }

		calcSWCSS();

		for (int i = 0; i < _clusters.length; i++)
		{
			_clusters[i].getCenter().calcCenter();
		}

		calcSWCSS();

		for (int i = 0; i < _iterator; i++)
		{
			for (int j = 0; j < _clusters.length; j++)
			{
				for (int k = 0; k < _clusters[j].NumOfPoints(); k++)
				{

					double tempEuDt = _clusters[j].getPoint(k).getCurrentDistance();
					Cluster tempCluster = null;
					boolean matchFoundFlag = false;

					for (int l = 0; l < _clusters.length; l++)
					{

						if (tempEuDt > _clusters[j].getPoint(k).checkDistance(_clusters[l].getCenter()))
						{
							tempEuDt = _clusters[j].getPoint(k).checkDistance(_clusters[l].getCenter());
							tempCluster = _clusters[l];
							matchFoundFlag = true;
						}
	
					}
	
					if (matchFoundFlag)
					{
						tempCluster.AddPoint(_clusters[j].getPoint(k));
						_clusters[j].RemovePoint(_clusters[j].getPoint(k));
						
						for (int m = 0; m < _clusters.length; m++)
						{
							_clusters[m].getCenter().calcCenter();
						}
						calcSWCSS();
					}
				}
			}
		}
	}

	public Vector<Point>[] ClusterOutput()
	{
		Vector<Point> v[] = new Vector[_clusters.length];
		for (int i = 0; i < _clusters.length; i++)
		{
			v[i] = _clusters[i].getPoints();
		}
		return v;
	}

	private void InitialCentroids()
	{
        double c[] = new double[MAX];

		for (int n = 1; n <= _clusters.length; n++)
		{

            for(int j=0;j<MAX; j++){
                c[j] = (((MaxValue(j) - MinValue(j)) / (_clusters.length + 1)) * n) + MinValue(j);
            }

			//Trace.Write("cx = " + cx + " cy = " + cy);
			ClusterCenter cc = new ClusterCenter(c);
			_clusters[n - 1].setCenter(cc);
			cc.setCluster(_clusters[n - 1]);
		}
	}


    private double MaxValue(int i){
        double temp;
        temp = ( _points.elementAt(0)).get(i);
        for (int j = 0; j < _points.size(); j++)
        {
            Point dp = _points.elementAt(j);
            temp = (dp.get(i) > temp) ? dp.get(i) : temp;
        }
        return temp;
    }

    private double MinValue(int i)
    {
        double temp = 0;
        temp = ( _points.elementAt(0)).get(i);
        for (int j = 0; j < _points.size(); j++)
        {
            Point dp = _points.elementAt(j);
            temp = (dp.get(i) < temp) ? dp.get(i) : temp;
        }
        return temp;
    }

	public int KValue()
	{
		return _clusters.length;
	}

	public int Iterations()
	{
		return _iterator;
	}

	public int TotalPoints()
	{
		return _points.size();
	}

	public double SWCSS()
	{
		return _SWCSS;
	}

	public Cluster getCluster(int pos)
	{
		return _clusters[pos];
	}
}